﻿
using System.Diagnostics.CodeAnalysis;

using Microsoft.Extensions.DependencyInjection;

using zijian666.DI.Features;

namespace zijian666.DI;


/// <summary>
/// 支持键值服务
/// </summary>
internal class KeyedServiceFeature : IKeyedServiceFeature
{
    public ServiceDescriptor CreateKeyedServiceDescriptor(Type serviceType, object? serviceKey, Type implementationType, ServiceLifetime lifetime)
    {
        return new ComponentServiceDescriptor(serviceType, serviceKey, implementationType, lifetime);
    }

    public ServiceDescriptor CreateKeyedServiceDescriptor(Type serviceType, object? serviceKey, Func<IServiceProvider, object?, object> factory, ServiceLifetime lifetime)
    {
        return new ComponentServiceDescriptor(serviceType, serviceKey, factory, lifetime);
    }

    public object GetKeyedService(IServiceProvider provider, Type implementationType, object? serviceKey)
    {
        if (provider is IKeyedServiceProvider keyedServiceProvider)
        {
            return keyedServiceProvider.GetKeyedService(implementationType, serviceKey)!;
        }
        return null;
    }
}


internal class ComponentServiceDescriptor : ServiceDescriptor
{
    public ComponentServiceDescriptor(Type serviceType, object instance) : base(serviceType, instance)
    {
    }

    public ComponentServiceDescriptor(Type serviceType, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType, ServiceLifetime lifetime) : base(serviceType, implementationType, lifetime)
    {
    }

    public ComponentServiceDescriptor(Type serviceType, object? serviceKey, object instance) : base(serviceType, serviceKey, instance)
    {
    }

    public ComponentServiceDescriptor(Type serviceType, Func<IServiceProvider, object> factory, ServiceLifetime lifetime) : base(serviceType, factory, lifetime)
    {
    }

    public ComponentServiceDescriptor(Type serviceType, object? serviceKey, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType, ServiceLifetime lifetime) : base(serviceType, serviceKey, implementationType, lifetime)
    {
    }

    public ComponentServiceDescriptor(Type serviceType, object? serviceKey, Func<IServiceProvider, object?, object> factory, ServiceLifetime lifetime) : base(serviceType, serviceKey, factory, lifetime)
    {
    }

    public override bool Equals(object? obj)
    {
        if (obj is not ComponentServiceDescriptor other)
        {
            return false;
        }
        return ServiceType == other.ServiceType
            && ImplementationType == other.ImplementationType
            && ImplementationInstance == other.ImplementationInstance
            && ImplementationFactory == other.ImplementationFactory
            && ServiceKey == other.ServiceKey
            && Lifetime == other.Lifetime;
    }
}